package com.xyy.saas.payment.adpater.jdCredit.callback;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jddglobal.open.client.DefaultSpiJddClient;
import com.xyy.saas.payment.adpater.jd.common.JDConstants;
import com.xyy.saas.payment.adpater.jd.utils.JDRequestUtils;
import com.xyy.saas.payment.adpater.jd.vo.JDNotifyRefundVo;
import com.xyy.saas.payment.adpater.jdCredit.enums.JdCreditPayStatusEnum;
import com.xyy.saas.payment.adpater.jdCredit.req.CreditResultNotifyReq;
import com.xyy.saas.payment.adpater.jdCredit.req.FinanceResultNotifyReq;
import com.xyy.saas.payment.adpater.jdCredit.support.JdCreditClientFactory;
import com.xyy.saas.payment.adpater.pingxx.domain.PayDO;
import com.xyy.saas.payment.adpater.pingxx.domain.RefundDO;
import com.xyy.saas.payment.callback.core.handler.CastRequestHandler;
import com.xyy.saas.payment.common.Constants;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.bo.jd.JDMerchantOneKeySignResultDto;
import com.xyy.saas.payment.cores.enums.JDPayTradeStatusEnum;
import com.xyy.saas.payment.cores.enums.ResultCodeEnum;
import com.xyy.saas.payment.dao.model.PrePayOrder;
import com.xyy.saas.payment.dao.model.RefundOrder;
import com.xyy.saas.payment.payment.core.service.PrePayOrderService;
import com.xyy.saas.payment.util.AmountCastUtil;
import com.xyy.saas.payment.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * 京东金融支付结果通知handler
 */
@Component
@Slf4j
public class CastJdCreditContractRequestHandler implements CastRequestHandler {
    @Autowired
    private PrePayOrderService prePayOrderService;

    @Override
    public String getChannel() {
        return JDConstants.JD_CREDIT_CONTRACT_CALLBACK_METHOD;
    }

    @Override
    public Object castRequestHandler(String method, Map<String, String> request, HttpServletRequest req) throws Exception {
        log.info("JdCreditPayCallBack接收到京东金融结果通知：解密前数据为 {}", method);
        DefaultSpiJddClient defaultSpiJddClient = JdCreditClientFactory.getDefaultSpiJddClient();

        String bizContent = defaultSpiJddClient.receive(req);
        log.info("CastJdCreditContract bizContent={}", bizContent);
        CreditResultNotifyReq creditResultNotifyReq = JSON.parseObject(bizContent, CreditResultNotifyReq.class);
        log.info("creditResultNotifyReq={}", creditResultNotifyReq);
        return creditResultNotifyReq;
    }

    /**
     * 协议签约：转换为协议签约结果通知
     */
    private JDMerchantOneKeySignResultDto castToContract(String body, JSONObject params) throws Exception {
        String logPrefix = "jdCardPayCastToContract ";
        JSONObject jsonObject = JDRequestUtils.verifySignAndDecryptReturn(logPrefix, params.getString("merchantNo"), body);
        log.info("{} 接收到京东协议结果通知：解密后数据为 {}", logPrefix, jsonObject);
        JDMerchantOneKeySignResultDto responseVo = JSON.toJavaObject(jsonObject, JDMerchantOneKeySignResultDto.class);
        if (StringUtils.isBlank(responseVo.getRequestNo())) {
            responseVo.setRequestNo(params.getString("reqNo"));
        }
        return responseVo;
    }

    /**
     * 退款：转换为退款结果通知
     */
    private RefundDO castToRefundDO(String body, JSONObject params) throws Exception {
        String logPrefix = "jdCardPayCastToRefundDO ";
        JSONObject jsonObject = JDRequestUtils.verifySignAndReturn(logPrefix, params.getString("merchantNo"), body);
        log.info("{} 接收到京东退款结果通知：解密后数据为 {}", logPrefix, jsonObject);
        JDNotifyRefundVo jdNotifyRefundVo = JSON.toJavaObject(jsonObject, JDNotifyRefundVo.class);
        if (!JDConstants.SUCCESS_CODE.equals(jdNotifyRefundVo.getResultCode()) || !JDPayTradeStatusEnum.effectiveStatus(jdNotifyRefundVo.getTradeStatus())) {
            log.error("{} 交易状态错误！", logPrefix);
            throw new Exception("交易状态错误！");
        }
        RefundDO refundDO = new RefundDO();
        // 基本参数
        refundDO.setRefundNo(jdNotifyRefundVo.getOutTradeNo());
        refundDO.setId(jdNotifyRefundVo.getTradeNo());
        refundDO.setOrderNo(jdNotifyRefundVo.getOutTradeNo());
        refundDO.setSucceed("SUCCESS".equalsIgnoreCase(transTradeStatus(jdNotifyRefundVo.getTradeStatus())) ? true : false);
        refundDO.setStatus(refundDO.getSucceed() ? RefundOrder.STATUS_FINISH : RefundOrder.STATUS_FAIL);
        refundDO.setTimeSucceed(StringUtils.isBlank(jdNotifyRefundVo.getFinishDate()) ? null : DateUtil.parase(jdNotifyRefundVo.getFinishDate(), DateUtil.DATEFORMATSECOND));
        refundDO.setFailureCode(jdNotifyRefundVo.getResultCode() + "|" + jdNotifyRefundVo.getResultDesc());
        refundDO.setFailureMsg(jdNotifyRefundVo.getResultDesc());
        return refundDO;
    }

    /**
     * 支付：转换为支付结果通知
     */
    private PayDO castToPayDO(HttpServletRequest request) throws Exception {

        //TODO 单例有没有问题
        DefaultSpiJddClient defaultSpiJddClient = JdCreditClientFactory.getDefaultSpiJddClient();
        String bizContent = defaultSpiJddClient.receive(request);
        log.info("bizContent={}", bizContent);
        FinanceResultNotifyReq jdNotifyTradeVo = JSON.parseObject(bizContent, FinanceResultNotifyReq.class);
        log.info("financeResultNotifyReq={}", jdNotifyTradeVo);
        /**
         * 业务方逻辑处理...
         */

        // 查询预支付订单
        PrePayOrder prePayOrder = prePayOrderService.getPrePayOrderByPayNo(jdNotifyTradeVo.getOrderCode());
        JSONObject extra = (StringUtils.isBlank(prePayOrder.getExtra()) ? new JSONObject() : JSONObject.parseObject(prePayOrder.getExtra()));
        // 基本参数
        PayDO payDO = new PayDO();
        //todo 商户号没有
//        payDO.setMchId(params.getString("merchantNo"));
        //todo 验证orderCode是不是payNo
        payDO.setOrderNo(jdNotifyTradeVo.getOrderCode());
//        payDO.setChannelChargeNo(jdNotifyTradeVo.getTradeNo());
        payDO.setAmount(AmountCastUtil.castYuan2Fen(jdNotifyTradeVo.getPayAmount()));
        payDO.setChannel(Constants.CHANNEL_JD_CREDIT);
        payDO.setPayMode(extra.getString("payMode"));
        payDO.setResultCode(transTradeStatus(jdNotifyTradeVo.getApplyStatus()));
        //借据单号
        payDO.setChannelTransactionNo(jdNotifyTradeVo.getLoanNo());
        payDO.setTimePaid(StringUtils.isBlank(jdNotifyTradeVo.getPayDate()) ? null : DateUtil.parase(jdNotifyTradeVo.getPayDate(), DateUtil.YYYYMMDDHHMMSS));
        //todo 失败码后面干啥用了
        //payDO.setFailureCode(jdNotifyTradeVo.getResultCode() + "|" + jdNotifyTradeVo.getResultDesc());
        payDO.setFailureMsg(jdNotifyTradeVo.getResDesc());
        // 其他参数
        payDO.setNotifyTime(DateUtil.now());
        payDO.setCount(0);
        payDO.setExtra(prePayOrder.getExtra());
        payDO.setBusinessType(prePayOrder.getBusinessType());
        payDO.setBusinessOrderType(prePayOrder.getBusinessOrderType());
        payDO.setReceiverId(prePayOrder.getReceiverId());
        payDO.setCallbackAddress(prePayOrder.getCallbackAddress());
        payDO.setPayer(prePayOrder.getPayer());
        return payDO;
    }

    /**
     * 转换交易状态
     */
    public static String transTradeStatus(String tradeStatus) throws PaymentException {
        if (tradeStatus.equals(JdCreditPayStatusEnum.PAID.getCode())) {
            return "SUCCESS";
        } else if (tradeStatus.equals(JdCreditPayStatusEnum.FAIL.getCode())) {
            return "FAIL";
        }
        throw new PaymentException(ResultCodeEnum.DEFAULT_ERROR, "交易状态错误");
    }

}
